import {defineStore} from "pinia";
import {CacheManager} from "@/cache";
import {MenuUtils} from "@/utils/MenuUtils";
import {toRaw} from "vue";
import {RouteLocationNormalized, RouteRecordRaw} from "vue-router";
import GlobalConstants from "@/constants/GlobalConstants";
import router from "@/router";

//布局菜单，所有非顶层路由都是该路由的子路由
const layoutMenu: RouteItem = {
  children: undefined,
  component: () => import('@/layouts/layout.vue'),
  componentName: "Layout",
  disabled: false,
  hidden: false,
  icon: "",
  id: "-1",
  isAffix: false,
  isTopPage: true,
  keepAlive: false,
  menuType: "router",
  name: "Layout",
  parent: undefined,
  path: "/layout",
  sort: -1,
  title: "Layout"
}
/**
 * 静态菜单，其中的路由会在初始化router对象时传入
 */
const staticMenus: Array<MenuRecordRaw> = [
  {
    title: '登录页面',
    menuType: 'router',
    path: GlobalConstants.LOGIN_PATH,
    component: '/system/LoginPage.vue',
    keepAlive: false,
    hidden: true,
    componentName: 'LoginPage',
    sort: 1,
    isTopPage: true
  },
  {
    title: '没有权限',
    menuType: 'router',
    path: '/401',
    component: '/error/401.vue',
    keepAlive: false,
    hidden: true,
    sort: 2,
    isTopPage: false
  },
  {
    title: '找不到此页面',
    menuType: 'router',
    path: '/:pathMatch(.*)*',
    component: '/error/404.vue',
    keepAlive: false,
    hidden: true,
    sort: Number.MAX_VALUE,
    isTopPage: false
  }
]
/**
 * 动态菜单，其中的路由通过addRouter动态添加，此数组一般通过后端接口获取，此处也可以用于通过前端写死动态路由
 */
const frontEndDynamicMenus: Array<MenuRecordRaw> = [
  {
    title: '首页',
    menuType: 'router',
    path: '/',
    icon: 'mdi-account-circle',
    component: '/system/TestPage.vue',
    keepAlive: true,
    hidden: false,
    componentName: 'Home',
    isAffix: true,
    sort: 0
  },
  {
    title: '用户管理',
    menuType: 'router',
    path: '/user',
    icon: 'mdi-account-circle',
    component: '/system/TestPage.vue',
    keepAlive: true,
    sort: 1,
    hidden: false,
    componentName: 'User',
    isAffix: false,
  },
  {
    title: '角色管理',
    menuType: 'router',
    path: '/role',
    icon: 'mdi-account-circle',
    component: '/system/TestPage.vue',
    keepAlive: true,
    hidden: false,
    componentName: 'Role',
    isAffix: false,
  },
  {
    title: '菜单管理',
    menuType: 'router',
    path: '/menu',
    icon: 'mdi-account-circle',
    component: '/system/TestPage.vue',
    keepAlive: true,
    hidden: false,
    componentName: 'Menu',
    isAffix: false,
  },
  {
    title: '系统管理',
    menuType: 'router',
    path: '/system',
    icon: 'mdi-account-circle',
    component: '/system/TestPage.vue',
    keepAlive: true,
    hidden: false,
    componentName: 'System',
    isAffix: false,
  },
  {
    title: '编辑器',
    menuType: 'router',
    path: '/editor',
    icon: 'mdi-account-circle',
    component: '/system/TestPage.vue',
    keepAlive: false,
    componentName: 'Editor',
    isAffix: false,
    disabled: false,
    isTopPage: false,
  },
  {
    title: '菜单1',
    menuType: 'dir',
    icon: 'mdi-account-circle',
    path: "/菜单1",
    disabled: false,
    children: [
      {
        title: '菜单1-2',
        menuType: 'router',
        path: '/path1-2',
        component: '/system/TestPage.vue',
        keepAlive: true,
        componentName: 'About',
        icon: 'mdi-account-circle',
        isAffix: false,
        isTopPage: false,
        children: [
          {
            title: '菜单1-2-1',
            menuType: 'router',
            path: '/path1-2-1',
            icon: 'mdi-account-circle',
            component: '/system/TestPage.vue',
            keepAlive: true,
            componentName: 'System',
            isAffix: false
          }
        ]
      },
    ]
  },
  {
    title: '跳转外部链接',
    path: "/跳转外部链接",
    disabled: true,
    menuType: 'link',
    oriURL: 'https://www.baidu.com',
    icon: 'location'
  },
  {
    title: 'Iframe',
    path: "/Iframe",
    menuType: 'iframe',
    disabled: false,
    oriURL: 'http://localhost:8080',
    icon: 'location'
  },
  {
    title: '大屏页面1',
    menuType: 'router',
    path: '/bigscreen1',
    icon: 'mdi-account-circle',
    component: '/system/TestPage.vue',
    keepAlive: false,
    componentName: 'bigscreen1',
    isAffix: false,
    disabled: false,
    isTopPage: true,
  },
  {
    title: '大屏页面2',
    menuType: 'router',
    path: '/bigscreen2',
    icon: 'mdi-account-circle',
    component: '/system/TestPage.vue',
    keepAlive: false,
    componentName: 'bigscreen2',
    isAffix: false,
    disabled: false,
    isTopPage: true,
  },
]
export const useMenuStore = defineStore('menu', {
  state: () => {
    return {
      //静态菜单，初始化之前都是原始数据
      staticMenus: staticMenus,
      //静态路由
      staticRouteSet: new Set<RouteRecordRaw>(),
      //动态菜单，初始化之前都是原始数据
      dynamicMenus: CacheManager.getDynamicMenus() as Array<MenuRecordRaw>,
      //动态路由
      dynamicRouteSet: new Set<RouteRecordRaw>(),
      //存储所有id和菜单映射关系
      menuMap: new Map<string, MenuRecordRaw>(),
      //存储所有的需要缓存的路由名字
      keepAliveNameSet: new Set<string>(),
      //是否加载动态路由完毕，每次刷新浏览器此属性的值都会重置为false，第二次进入全局路由守卫时需要一个标识用于退出
      loadingComplete: false,
      //选项卡列表
      tabItems: CacheManager.getTabItems(),
      //标签页历史记录
      tabHistory: CacheManager.getTabHistory(),
      //当前激活的选项卡
      activeTab: ''
    }
  },
  actions: {
    /**
     * 初始化静态菜单
     * @return  Array<RouteRecordRaw> 返回静态路由数组
     */
    initStaticMenus(): Array<RouteRecordRaw> {
      MenuUtils.processList(toRaw(this.staticMenus), this.menuMap, this.staticRouteSet, this.keepAliveNameSet)
      //顶层路由
      const topRoutes: Array<RouteRecordRaw> = []
      //子路由
      const childrenRoutes: Array<RouteRecordRaw> = []
      toRaw(this.staticRouteSet).forEach(route => {
        if (route.meta?.isTopPage) {
          topRoutes.push(route);
        } else {
          childrenRoutes.push(route)
        }
      })

      const layoutMenuSet = new Set<RouteRecordRaw>()
      MenuUtils.processList([layoutMenu], undefined, layoutMenuSet)
      const layoutRoute = Array.from(layoutMenuSet)[0]
      layoutRoute.children = childrenRoutes
      topRoutes.push(layoutRoute)
      return topRoutes
    },
    /**
     * 初始化所有动态路由，包括前端配置或者后端接口获取的
     */
    async initDynamicMenus() {
      if (this.dynamicMenus.length === 0) {
        //后端动态路由，通过调用接口获取，todo 如果要从后端接口获取路由，只需要改这一行代码
        const backEndDynamicMenus = await Promise.resolve<Array<MenuRecordRaw>>([])
        //所有动态路由
        this.dynamicMenus = MenuUtils.processId([...frontEndDynamicMenus, ...backEndDynamicMenus])
        //后端菜单生成id，统一保存
        CacheManager.setDynamicMenus(this.dynamicMenus)
      }
      MenuUtils.processList(toRaw(this.dynamicMenus), this.menuMap, this.dynamicRouteSet, this.keepAliveNameSet)
      //顶层路由
      const topRoutes: Array<RouteRecordRaw> = []
      //子路由
      const childrenRoutes: Array<RouteRecordRaw> = []
      toRaw(this.dynamicRouteSet).forEach(route => {
        if (route.meta?.isTopPage) {
          topRoutes.push(route);
        } else {
          childrenRoutes.push(route)
        }
      })
      topRoutes.forEach(route => {
        router.addRoute(route)
      })
      childrenRoutes.forEach(childRoute => {
        router.addRoute(layoutMenu.name as string, childRoute)
      })
      //初始化选项卡
      if (this.tabItems.size === 0 && this.tabHistory.length === 0) {
        Array.from(this.menuMap.values())
          //只有路由才会有标签页
          .filter((item) => item.menuType === 'router')
          .map(value => value as RouteItem)
          //下面三个筛选条件都是为了保证该路由可以由菜单树直接进入
          //路由不允许被禁用
          .filter(item => !item.disabled)
          //路由不允许被隐藏
          .filter(item => !item.hidden)
          .filter(item => {
            //这里是为了排除一个路由下的多个子页面。例如新增页面或者编辑页面的路由
            if (!item.parent) {
              return true;
            } else {
              return item.parent.menuType === 'dir'
            }
          })
          //筛选出初始时需要固定的路由
          .filter(item => item.isAffix)
          //顶级路由不需要固定
          .filter(item => !item.isTopPage)
          .sort((child1, child2) => (child1.sort as number) - (child2.sort as number))
          .map(item => {
            return {
              id: item.id as string,
              isAffix: true,
              path: item.path,
              title: item.title,
              icon: item.icon
            } as TabItem
          }).forEach(item => {
          this.tabItems.add(item)
        });
        if (this.tabItems.size === 0) {
          throw new Error("至少有一个长期固定的选项卡，例如首页");
        }
        CacheManager.setTabItems(this.tabItems)
      }
      this.loadingComplete = true;
    },
    //关闭选项卡
    async closeTab(item: TabItem) {
      if (item.isAffix) {
        //此类选项卡长期固定，不可关闭
        return
      }
      this.tabItems.delete(item);
      CacheManager.setTabItems(this.tabItems)
      //清除与该选项卡相关的历史记录
      this.tabHistory = this.tabHistory.filter(value => value != item.id);
      this.clearAndSaveHistory()
      //关闭当前标签页
      if (item.id === this.activeTab) {
        const to = this.tabHistory.pop()
        this.clearAndSaveHistory()
        await this.pushRouter(to)
      }
    },
    //跳转到指定ID的路由，不传则跳转到第一个固定选项卡
    async pushRouter(id?: string) {
      if (!id) {
        //跳转到第一个被固定的选项卡
        await router.push(Array.from(this.tabItems)[0].path);
      } else {
        const menu = this.menuMap.get(id);
        if (!menu) {
          return Promise.reject(`路由不存在：${id}`);
        } else if (menu.menuType === 'router' || menu.menuType === 'iframe') {
          await router.push(menu.path as string);
        }
      }
    },
    //记录跳转历史，只记录需要保存到选项卡的历史
    pushHistory(to: RouteLocationNormalized) {
      if (to.meta.parentMenuType === 'iframe' || to.meta.parentMenuType === 'router') {
        //当前路由是新增编辑之类的路由页面，应该激活对应的列表页面
        //当前路由对应的原始菜单配置
        let menu: ParentMenuRecordRaw | undefined | null = to.meta.menu as ParentMenuRecordRaw
        while (menu?.parent?.menuType === 'iframe' || menu?.parent?.menuType === 'router') {
          menu = menu?.parent
        }
        if (menu) {
          if (menu.menuType === 'router' && menu.isTopPage) {
            return;
          }
          if (menu.disabled || menu.hidden) {
            return;
          }
          if (Array.from(this.tabItems).find(value => value.id === menu.id)) {
            this.activeTab = menu.id as string;
          }
        }
        return;
      } else if (to.meta.disabled || to.meta.isTopPage || to.meta.hidden) {
        return;
      } else {
        this.activeTab = to.meta.id
        //选项卡已经打开，则不保存
        if (!Array.from(this.tabItems).find(value => value.id === to.meta.id)) {
          const tabItem: TabItem = {
            id: to.meta.id,
            isAffix: to.meta.isAffix,
            path: to.meta.path,
            title: to.meta.title,
            icon: to.meta.icon
          };
          this.tabItems.add(tabItem);
          CacheManager.setTabItems(this.tabItems);
        }
        this.tabHistory.push(to.meta.id);
        this.clearAndSaveHistory()
      }
    },
    //tabHistory中的数据有改变时都应该调用此方法
    clearAndSaveHistory() {
      //保证不会出现两个连续相同的历史记录
      this.tabHistory = this.tabHistory.filter((tab, index, array) => {
        return index === 0 || tab !== array[index - 1];
      });
      CacheManager.setTabHistory(this.tabHistory)
    },
  },
  getters: {
    allMenus(state) {
      return MenuUtils.sort([...state.staticMenus, ...state.dynamicMenus])
    },
    maxLevel(state): number {
      const sortArray = Array.from(toRaw(state.menuMap).values())
        .filter(value => value.hidden !== true && value.disabled !== true)
        .sort((child1, child2) => (child2.level as number) - (child1.level as number));
      if (sortArray.length) {
        return sortArray[0].level as number
      } else {
        return 1
      }
    },
  }
});
